package com.ljc.websocket.chat;

import com.fasterxml.jackson.databind.util.JSONPObject;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOError;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 * @author liujuncheng
 * @since 2021-01-02 12:51
 * @描述：处理websocket
 */
@ServerEndpoint("/chatWebSocket/{userName}")
@Component
public class ChatServerEndPoint {

    /***
     * 在线人数
     */
    public static int onlineNumber = 0;

    /**
     * 以用户姓名为key ,ChatServerEndPoint 为对象保存起来
     */
    private static Map<String,ChatServerEndPoint> clients = new ConcurrentHashMap<>();

    /**
     * 会话
     */
    private Session session;
    /**
     * 用户名称
     */
    private String userName ;
    /**
     * 建立连接
     * @param session
     */
    @OnOpen
    public void onOpne(@PathParam("userName") String userName, Session session){

        onlineNumber++;
        this.userName = userName;
        this.session = session;
        System.out.println("有新连接加入！当前在线人数："+onlineNumber);
        try {
            //messageType 1 表示上线 2代表下线 3代表在线名单 4 代表普通消息
            Map<String,Object> map = new HashMap<>();
            map.put("messageType",1);
            map.put("userName",userName);
            map.put("onlineNumber",onlineNumber);
            //map 转 json
            Gson gson = new Gson();
            //发送通知给自己
            sendMessageAll(gson.toJson(map),userName);
            clients.put(userName,this);
            Map<String,Object> map2 = new HashMap<>();
            map2.put("messageType",3);
            Set<String> set = clients.keySet();
            map2.put("onlineUsers",set);
            map2.put("onlineNumber",onlineNumber);
            sendMessageTo(gson.toJson(map2),userName);
        }catch (Exception e){
            System.out.println(userName+"上线时，通知所有人发生错误！");
        }
        System.out.println("连接创建成功！");
    }

    @OnError
    public void onError(Session session,Throwable throwable){
        System.out.println("服务端发生了错误："+ throwable.getMessage());
    }

    /**
     * 关闭连接
     * @param session
     */
    @OnClose
    public void onClose(Session session){

        onlineNumber--;
        clients.remove(userName);
        try {
            Map<String,Object> map = new HashMap<>();
            map.put("messageType",2);
            map.put("onlineUsers",clients.keySet());
            map.put("userName",userName);
            map.put("onlineNumber",onlineNumber);
            Gson gson = new Gson();
            sendMessageAll(gson.toJson(map),userName);
        }catch (Exception e){
            System.out.println(userName+"下线时通知所有人发生错误！");
        }
        System.out.println("连接关闭！当前在线人数："+onlineNumber);
    }

    /**
     * 接收客户端消息消息
     * @param message 来自客户端消息
     * @param session
     * @return
     */
    @OnMessage
    public void onMessage(String message,Session session){

        try {
            System.out.println("来自客户端消息："+message +",来自客户端id:"+session.getId());
            Gson gson = new Gson();
            Map<String,Object> map = new HashMap<>();
            map = gson.fromJson(message,Map.class);
            map.put("messageType",4);//普通消息
            if(map.get("toUserName").toString().equals("All")){
                map.put("toUserName","所有人");
                sendMessageAll(gson.toJson(map),map.get("userName").toString());
            }else {
                //map.put("toUserName",map.get("toUserName"));
                sendMessageTo(gson.toJson(map),map.get("toUserName").toString());
            }
        }catch (Exception e){
            System.out.println("发送消息发生了错误！");
        }
        //return "server 发送："+message;
    }


    /**
     * 发送信息给  toUserName
     * @param message 需要发送的消息
     * @param toUserName 消息接收人
     */
    public void sendMessageTo(String message,String toUserName){
        for(ChatServerEndPoint item : clients.values()){
            if(item.userName.equals(toUserName)){
                item.session.getAsyncRemote().sendText(message);
                break;
            }
        }
    }

    /**
     * 发送消息给所有人
     * @param message  需要发送的消息
     * @param fromUserName 消息发送人
     */
    public void sendMessageAll(String message,String fromUserName){
        for(ChatServerEndPoint item : clients.values()){
            item.session.getAsyncRemote().sendText(message);
        }
    }
}
